import type { FC } from 'react';
import { useRef, useEffect, useContext } from 'react';
import { useMemoizedFn, useSafeState } from 'ahooks';
import { initSearch, searchByKeywords, setCenterByPos } from './helper';
import { Form, Input, message, List, Space, Button } from 'antd';
import type { MapRes, PoiItem, PlaceSearch, PageType } from './types';
import type { MapControlProps } from './index';

import Context from './context';
import ResultItem from './result';
import styles from './styles.module.less';

type SearchBarProps = {
  control: MapRes;
  defaultValue: MapControlProps["defaultValue"];
}

const SearchBar: FC<SearchBarProps> = (props) => {
  const { control, defaultValue } = props;
  const [form] = Form.useForm();
  const search = useRef<PlaceSearch>();
  const [loading, setLoading] = useSafeState(false);
  const { selectedPoi, setSelectedPoi } = useContext(Context);
  const [pagination, setPagination] = useSafeState<PageType>();
  const [dataSource, setDataSource] = useSafeState<PoiItem[]>([]);

  // 设置中心点
  const setCenter = useMemoizedFn((pio?: PoiItem) => {
    if (pio) setCenterByPos(control, [
      pio.location.lng, pio.location.lat
    ]);
  });

  // 提交
  const handleSubmit = useMemoizedFn(async () => {
    const _search = search.current;
    const { keywords } = form.getFieldsValue();

    if (!_search || !keywords) {
      return;
    }

    setLoading(true);
    try {
      const [
        dataSource,
        pagination
      ] = await searchByKeywords(
        keywords, _search
      );
      setDataSource(dataSource);
      setPagination(pagination);
    } catch (err) {
      if (err instanceof Error) {
        message.error(err.message);
        return Promise.reject(err);
      }
    } finally {
      setLoading(false);
    }
  });

  const handlePageChange = useMemoizedFn(
    (pageSize: number) => {
      const _search = search.current;
      if (_search) {
        _search.setPageIndex(pageSize);
        handleSubmit();
      }
    }
  );

  const initCenter = useMemoizedFn(async () => {
    if (!defaultValue) {
      return;
    }

    const address = [
      defaultValue.province,
      defaultValue.city,
      defaultValue.district,
      defaultValue.street
    ].join('');

    form.setFieldsValue({
      keywords: address
    });

    await handleSubmit();

    setCenterByPos(control, [
      defaultValue.longitude,
      defaultValue.latitude
    ]);
  });

  // 初始化搜索
  const initialization = useMemoizedFn(() => {
    initSearch(control).then(e => {
      search.current = e;
      initCenter();
    });
  });

  useEffect(initialization, [initialization]);
  useEffect(() => setCenter(selectedPoi), [selectedPoi]);

  return (
    <div className={styles.search}>
      <Form
        form={form}
        onFinish={handleSubmit}
        className={styles.search_form}
      >
        <Space.Compact style={{ width: '100%' }}>
          <Form.Item noStyle name="keywords">
            <Input placeholder="请输入" />
          </Form.Item>
          <Button
            children="搜索"
            type="primary"
            htmlType="submit"
          />
        </Space.Compact>
      </Form>
      <List
        loading={loading}
        dataSource={dataSource}
        className={styles.search_result}
        pagination={dataSource.length ? {
          ...pagination,
          size: 'small',
          showSizeChanger: false,
          onChange: handlePageChange,
          showTotal: (total) => (
            <span className={styles.total}>
              总{total}条
            </span>
          )
        } : false}
        renderItem={item => {
          return (
            <ResultItem
              poi={item}
              key={item.id}
              onClick={setSelectedPoi}
              selectedPio={selectedPoi}
            />
          );
        }}
      />
    </div>
  );
}

export default SearchBar;
